package capture
/**
 * Created by IntelliJ IDEA.
 * User: Maciej Szawlowski
 * Date: 27.09.11
 * Time: 18:37
 * To change this template use File | Settings | File Templates.
 */
public final class OptionManager {
    boolean init = true

    boolean captureNetworkMalicious = false
    boolean captureNetworkBenign = false
    boolean collectModified = false

    boolean processListLoaded = false
    boolean fileListLoaded = false
    def processExclusionList = ['-': [:], '+': [:]]
    def fileExclusionList = [
            '-': ['Delete': [:], 'Write': [:], 'Open': [:], 'Read': [:], 'Create': [:]],
            '+': ['Delete': [:], 'Write': [:], 'Open': [:], 'Read': [:], 'Create': [:]]
    ]

    String serverIp = "localhost"
    int serverPort = 1337
    Double server

    long serverId
    long id
    int socketTimeout = 5000

    String program
    int programTimeout
    String identifier

    def urlMap = [:]
    String startTime
    int malicious = 0
    int majError = 0
    int minError = 0
    int visited = 0

    def processMap = [:]
    //key = process id, val = fd map
    def fdMap = [:]
    def specialFdMap = [:]
    def cloexecMap = [:]
    def unfinishedLines = [:]


    private final static OptionManager instance = new OptionManager()

    private OptionManager() {

    }

    void loadExclusionList(String path, ExclusionListType type) {
        File file = new File(path)
        if (file.exists()) {
            def attrs
            println "Loading file: [${file.path}]"
            if (type == ExclusionListType.FILE) {
                println "File exclusion list [${file.path}] succesfully loaded."
                fileListLoaded = true
            } else {
                println "Process exclusion list [${file.path}] succesfully loaded."
                processListLoaded = true
            }
            int lineNo = 1
            file.eachLine { line ->
                attrs = line.split()
                if (line.indexOf('#') < 0 && line.size() > 0) {

                    if (type == ExclusionListType.FILE && attrs.size() == 4) {
                        addFileExclusion(attrs[0], attrs[1], attrs[3], attrs[2])
                    } else if (type == ExclusionListType.PROCESS && attrs.size() == 4) {
                        addProcessExclusion(attrs[0], attrs[3], attrs[2])
                    } else {
                        println "Line [$lineNo] malformed: [$line]"
                    }
                }
                ++lineNo
            }
        }
    }

    void addProcessExclusion(String exclusionType, String subject, String regex) {
        if (!(exclusionType in ['-', '+'])) {
            println "Error in process exclusion [$exclusionType] [$regex] [$subject]"
            return
        }
        if (!processExclusionList[exclusionType][subject]) {
            processExclusionList[exclusionType][subject] = []
        }
        processExclusionList[exclusionType][subject].push(~/$regex/)
    }

    void addFileExclusion(String exclusionType, String action, String regex, String subject) {
        if (!(action in ['Read', 'Open', 'Create', 'Delete', 'Write']) || !(exclusionType in ['-', '+'])) {
            println "Error in file exclusion [$exclusionType] [$action] [$regex] [$subject]"
            return
        }

        if (!fileExclusionList[exclusionType][action][subject]) {
            fileExclusionList[exclusionType][action][subject] = []
        }
        fileExclusionList[exclusionType][action][subject].push(~/$regex/)
    }

    //params - for files [action: write,read,etc; path: /usr/bin/smthn ]  for process (process path)
    boolean isExcluded(ExclusionListType type, def params) {                    //alarm
        return processList('-', type, params)
    }

    boolean isIncluded(ExclusionListType type, def params) {    //dont alarm
        return processList('+', type, params)
    }

    boolean processList(String listType, ExclusionListType type, def params) {
        def list
        switch (type) {
            case [ExclusionListType.FILE]:
                list = fileExclusionList
                boolean ret = false
                if (list[listType][params.action][params.subject]?.size() > 0) {
                    for (path in list[listType][params.action][params.subject]) {
                        if (params.path ==~ path) {
                            ret = true
                            break
                        }
                    }
                }
                return ret
            case [ExclusionListType.PROCESS]:
                list = processExclusionList
                boolean ret = false

                if (list[listType][params.subject]?.size() > 0) {
                    for (object in list[listType][params.subject]) {
                        if (params.object ==~ object) {
                            ret = true
                            break
                        }
                    }
                }
                return ret
        }

    }

    static OptionManager getInstance() {
        return instance
    }

    String buildCommand() {
        def ret = []
        ret.push(program)
        urlMap.each {k, v ->
            ret.push(k)
        }
        return ret.join(' ')

    }

    //dbg purpose
    String toString() {
        def ret = ["Options:"]
        this.properties.each {['class', 'metaClass', 'instance'].contains(it.key) ? "" : ret.push("$it.key: $it.value")}

        return ret.join('\n\t\t')
    }
}

enum ExclusionListType {
    PROCESS, FILE
}
